#1.导包
import pandas as pd
import numpy as np
import xgboost as xgb
from collections import Counter
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split,GridSearchCV, StratifiedKFold
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import classification_report, accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
from sklearn.utils import class_weight
from xgboost import plot_importance
import matplotlib.pyplot as plt
#2.加载数据
data = pd.read_csv('D:/01_人才流失实战/人才流失预测/train.csv')
#3.了解数据
print(data.head())
print(data.info()) #TODO 一共31列数据 其中 标签为'Attrition'--离职与否
print(data.columns) #TODO 其中int类型的列一共23个，object类型的列有8个
print(data.value_counts('Attrition'))
print('=========================================================================================')
#4.数据预处理
#4.1处理缺失数据
print(data.isnull().sum())
# TODO 缺失数据为0
#4.2处理非数据形特征
# TODO 一共有8类特征为非数据类型 1.BusinessTravel 2.Department 3.EducationField 4.Gender 5.JobRole 6.MaritalStatus 7.Over18 8.OverTime
#处理1.BusinessTravel ['Travel_Rarely' 'Travel_Frequently' 'Non-Travel']
data.replace('Non-Travel',0,inplace=True)
data.replace('Travel_Rarely',1,inplace=True)
data.replace('Travel_Frequently',2,inplace=True)
#处理2.Department ['Research & Development' 'Sales' 'Human Resources']
data.replace('Human Resources',0,inplace=True)
data.replace('Research & Development',1,inplace=True)
data.replace('Sales',2,inplace=True)
#处理3.EducationField ['Life Sciences' 'Medical' 'Other' 'Technical Degree' 'Human Resources'  'Marketing']
data.replace('Life Sciences',0,inplace=True)
data.replace('Medical',1,inplace=True)
data.replace('Marketing',2,inplace=True)
data.replace('Technical Degree',3,inplace=True)
data.replace('Other',4,inplace=True)
#处理4.Gender ['Male' 'Female']
data.replace('Male',0,inplace=True)
data.replace('Female',1,inplace=True)
#处理5.JobRole ['Manufacturing Director' 'Laboratory Technician' 'Sales Executive' 'Research Scientist' 'Healthcare Representative' 'Human Resources' 'Sales Representative' 'Research Director' 'Manager']
data.replace('Manufacturing Director',0,inplace=True)
data.replace('Laboratory Technician',1,inplace=True)
data.replace('Sales Executive',2,inplace=True)
data.replace('Research Scientist',3,inplace=True)
data.replace('Healthcare Representative',4,inplace=True)
data.replace('Human Resources',5,inplace=True)
data.replace('Sales Representative',6,inplace=True)
data.replace('Research Director',7,inplace=True)
data.replace('Manager',8,inplace=True)
#处理6.MaritalStatus ['Divorced' 'Single' 'Married']
data.replace('Divorced',0,inplace=True)
data.replace('Single',1,inplace=True)
data.replace('Married',2,inplace=True)
#处理7.Over18 只有 Y 直接删除
data = data.drop(columns=['Over18'])
#处理8.OverTime ['No' 'Yes']
data.replace('No',0,inplace=True)
data.replace('Yes',1,inplace=True)


data = data.drop(columns=['PerformanceRating', 'StandardHours'])
'''
data=data.drop(columns=['StandardHours'])
'''
print('------------------------------------------------------------------------')

#5.特征工程
features=data.iloc[:,1:]
labels=data.iloc[:,0]

#初始化标准化器
scaler = StandardScaler()
#对特征进行标准化（fit + transform）
features_scaled = scaler.fit_transform(features)
x_train, x_test, y_train, y_test = train_test_split(features_scaled, labels, test_size=0.2, random_state=34,stratify=labels)


#相关性分析
print('==================================================================')
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
import matplotlib.pyplot as plt

rf = RandomForestClassifier(n_estimators=100, random_state=34)

# 训练模型
rf.fit(features, labels)

# 获取特征重要性
importances = rf.feature_importances_

# 将特征重要性转换为 DataFrame 显示
feature_names = features.columns
feat_importances = pd.Series(importances, index=feature_names)
feat_importances.nlargest(10).plot(kind='barh')
plt.title('Top 10 Feature Importances')
plt.show()

print(feat_importances.sort_values(ascending=False))
# TODO 'PerformanceRating', 'StandardHours'两个数据重要程度低于1%可以去除
print('==================================================================')

#6.创建模型
#定义要搜索的超参数空间
param_grid = {
    'n_estimators': [450],
    'max_depth': [4],
    'min_child_weight': [12],
    'gamma': [0],
    'learning_rate': [0.1],
    'subsample': [0.8],
    'reg_alpha': [1],  # L1 正则
    'reg_lambda': [0.1],   # L2 正则
    'colsample_bytree': [0.8]
}
#设置网格搜索 + 交叉验证
model = xgb.XGBClassifier(
    objective='binary:logistic',
    eval_metric='logloss',  # 避免警告
    use_label_encoder=False,  # 禁用标签编码器以避免警告
    class_weight='balanced'
)
# 设置交叉验证策略
cv_strategy = StratifiedKFold(n_splits=5, shuffle=True, random_state=34)

# 设置网格搜索
grid_search = GridSearchCV(
    estimator=model,
    param_grid=param_grid,
    scoring='roc_auc',         # 可替换为 f1、roc_auc 等
    cv=cv_strategy,
    verbose=1,
    n_jobs=-1
)
#执行网格搜索训练
grid_search.fit(x_train, y_train)

'''
#选择xgboost模型
estimator = xgb.XGBClassifier(n_estimators=100, max_depth=6, learning_rate=0.3, objective='binary:logistic')

#7.训练模型
estimator.fit(x_train, y_train)
'''
print('===========================================================================================================')
#8.处理测试集数据
test_data = pd.read_csv('D:/01_人才流失实战/人才流失预测/test2.csv')
#处理1.BusinessTravel ['Travel_Rarely' 'Travel_Frequently' 'Non-Travel']
test_data.replace('Non-Travel',0,inplace=True)
test_data.replace('Travel_Rarely',1,inplace=True)
test_data.replace('Travel_Frequently',2,inplace=True)
#处理2.Department ['Research & Development' 'Sales' 'Human Resources']
test_data.replace('Human Resources',0,inplace=True)
test_data.replace('Research & Development',1,inplace=True)
test_data.replace('Sales',2,inplace=True)
#处理3.EducationField ['Life Sciences' 'Medical' 'Other' 'Technical Degree' 'Human Resources'  'Marketing']
test_data.replace('Life Sciences',0,inplace=True)
test_data.replace('Medical',1,inplace=True)
test_data.replace('Marketing',2,inplace=True)
test_data.replace('Technical Degree',3,inplace=True)
test_data.replace('Other',4,inplace=True)
#处理4.Gender ['Male' 'Female']
test_data.replace('Male',0,inplace=True)
test_data.replace('Female',1,inplace=True)
#处理5.JobRole ['Manufacturing Director' 'Laboratory Technician' 'Sales Executive' 'Research Scientist' 'Healthcare Representative' 'Human Resources' 'Sales Representative' 'Research Director' 'Manager']
test_data.replace('Manufacturing Director',0,inplace=True)
test_data.replace('Laboratory Technician',1,inplace=True)
test_data.replace('Sales Executive',2,inplace=True)
test_data.replace('Research Scientist',3,inplace=True)
test_data.replace('Healthcare Representative',4,inplace=True)
test_data.replace('Human Resources',5,inplace=True)
test_data.replace('Sales Representative',6,inplace=True)
test_data.replace('Research Director',7,inplace=True)
test_data.replace('Manager',8,inplace=True)
#处理6.MaritalStatus ['Divorced' 'Single' 'Married']
test_data.replace('Divorced',0,inplace=True)
test_data.replace('Single',1,inplace=True)
test_data.replace('Married',2,inplace=True)
#处理7.Over18 只有 Y 直接删除
test_data=test_data.drop(columns=['Over18'])
#处理8.OverTime ['No' 'Yes']
test_data.replace('No',0,inplace=True)
test_data.replace('Yes',1,inplace=True)


test_data = test_data.drop(columns=['PerformanceRating', 'StandardHours'])
'''
test_data=test_data.drop(columns=['StandardHours'])
'''
#9.使用最佳模型进行预测和评估
best_model = grid_search.best_estimator_
y_predict = best_model.predict(x_test)
y_predict_pro = grid_search.predict_proba(x_test)
y_predict_pro = y_predict_pro[:, 1]

print(f'预测结果为: {y_predict}')
print(f'正确率: {accuracy_score(y_test, y_predict)}')
print('==========================================')
print(f"准确率(accuracy):{accuracy_score(y_test, y_predict)}")
print(f"精确率(precision):{precision_score(y_test, y_predict, pos_label=0)}")
print(f"召回率(recall):{recall_score(y_test, y_predict, pos_label=0)}")
print(f"f1分数:{f1_score(y_test, y_predict, pos_label=0)}")
print(f"roc_auc_score:{roc_auc_score(y_test, y_predict_pro)}")
#11.数据可视化
print('======================================================================')
# 展示最佳参数
print(best_model.get_params(deep=True))
# 绘制特征重要性图
from xgboost import plot_importance
import matplotlib.pyplot as plt

plot_importance(best_model)
plt.show()
print('================================================================================')
# TODO 我啥也看不出来



































